
local meta = FindMetaTable( "Player" );

function meta:Initialize()

	if( self:IsBot() ) then return end

	local ply = self;
	
	ply:SetTeam( 1 ); 
	ply:SnapOutOfStance();
	
	--VAR INITIALIZATION--
	
	ply:GetTable().Initialized = false; 
	ply:GetTable().HasSeenMOTD = false; 
	ply:SetNWBool( "IsTyping", false ); 
	ply:GetTable().ProcessBars = { }; 
	
	ply:GetTable().AttachedProps = { }
	
	ply:GetTable().AnimLastModel = "";
	ply:GetTable().LastWeapon = "";
	 
	ply:GetTable().SendItemNames = { }
	
	ply:GetTable().NextTimeCanChat = 0;
	ply:GetTable().NextTimeCanChatOOC = 0;
	
	ply:GetTable().CanUseDuplicator = false;
	
	ply:GetTable().LastCharCreateMenu = 0;
	ply:GetTable().LastCharCreation = 0;
	ply:GetTable().LastFlashSwitch = 0;
	ply:GetTable().LastStanceAction = 0;
	ply:GetTable().LastMOTDPrompt = 0;
	ply:GetTable().LastStorageItemAdd = 0;
	ply:GetTable().LastTargetIDUpdate = 0;
	ply:GetTable().LastItemUse = 0;
	ply:GetTable().LastKeyPress = 0;
	ply:GetTable().LastF4 = 0;
	ply:GetTable().LastHelp = 0;
	ply:GetTable().LastConsciousRecover = 0;
	ply:GetTable().InGame = false
	
	ply:Observe( false );
	
	ply:SetPlayerBleeding( false );
	ply:SetPlayerCanSprint( true );
	ply:SetPlayerConscious( true );
	
	ply:GetTable().ItemsDownloaded = { }
	
	--END VAR INITIALIZATION--
	
	ply:MakeInvisible();
	ply:Lock();
	
	
	timer.Simple( .5, ply.CrosshairDisable, ply );
	timer.Simple( .6, ply.DrawViewModel, ply, false ); 
	
	--Comment out this line if we aren't debugging
	--local debugging = true;
	
	if( not debugging ) then
	
		--Delay so that it doesn't fuck up
		timer.Simple( 1, ply.PromptAccountMenu, ply );
	
	else
	
		ply:CharacterInitialize();
		umsg.Start( "EFGI", ply ); umsg.End();
		
		ply:GetTable().CanInitialize = true;
		ply:GetTable().HasSeenMOTD = true;
	
	end

end

function GM:PlayerInitialSpawn( ply )

	if( ply:IsBot() ) then return end

	ply:SetField( "charid", -1 );
	ply:SetField( "UniqueID", math.random( 0, 1000 ) );

	umsg.Start( "setUniqueID", ply );
		umsg.Short( ply:GetField( "UniqueID" ) );
	umsg.End();
	
	ply:SetNWString( "SteamID", ply:SteamID() )
	ply:SetNWString( "RPName", "Connecting" )		

	--timer.Simple( .1, ply.HandleUID, ply )
	timer.Simple( .1, function()
	
		ply:HandleUID( false )
		
	end )	

end	

function meta:RefreshShit()
	
	local ply = self;
	
	--Inventories
	ply:GetTable().Inventories = { }
	
	--Just a list of the items in our inventory
	ply:GetTable().InventoryList = { }
	
	--Serverside inventory grid.  CPU lag?  We'll see.
	ply:GetTable().InventoryGrid = { }
	
	for n = 1, TS.MaxInventories do
		
		ply:GetTable().Inventories[n] = { }
		ply:GetTable().Inventories[n].Name = "";
		ply:GetTable().Inventories[n].Width = 9;
		ply:GetTable().Inventories[n].Height = 6;
	
		ply:GetTable().InventoryGrid[n] = { }
	
		for x = 0, 8 do
		
			ply:GetTable().InventoryGrid[n][x] = { }
		
			for y = 0, 5 do
			
				ply:GetTable().InventoryGrid[n][x][y] = { }
				ply:GetTable().InventoryGrid[n][x][y].Filled = false;
			
			end
			
		end
		
	end
	
	ply:CallEvent( "ResetInventory" );
	
	ply:SetField( "CombineFlags", "" )
	ply:SetField( "PlayerFlags", "" )
	
	timer.Simple( .3, ply.Die, ply )

end

function meta:CharacterInitialize()
	
	local ply = self;
	
	if( ply:IsBot() ) then return end
	
	--Inventories
	ply:GetTable().Inventories = { }
	
	--Just a list of the items in our inventory
	ply:GetTable().InventoryList = { }
	
	--Serverside inventory grid.  CPU lag?  We'll see.
	ply:GetTable().InventoryGrid = { }
		
	for n = 1, TS.MaxInventories do
		
		ply:GetTable().Inventories[n] = { }
		ply:GetTable().Inventories[n].Name = "";
		ply:GetTable().Inventories[n].Width = 9;
		ply:GetTable().Inventories[n].Height = 6;
	
		ply:GetTable().InventoryGrid[n] = { }
	
		for x = 0, 8 do
		
			ply:GetTable().InventoryGrid[n][x] = { }
		
			for y = 0, 5 do
			
				ply:GetTable().InventoryGrid[n][x][y] = { }
				ply:GetTable().InventoryGrid[n][x][y].Filled = false;
			
			end
			
		end
		
	end
	
	ply:CallEvent( "ResetInventory" );
	
	ply:SetPlayerSprint( 100 );
	ply:SetPlayerConsciousness( 100 );
	ply:SetPlayerMoney( 200 );
	ply:SetPlayerBleeding( false );
	ply:SetPlayerCanSprint( true );
	ply:SetPlayerConscious( true );
	
	ply:SetHealth( 100 );
	ply:GetTable().MaxHealth = 100;
	
	ply:GetTable().OutOfMenu = true
	
	ply:GetTable().StatusIsInjured = false;
	ply:GetTable().StatusIsCrippled = false;
	ply:GetTable().IsTied = false;
	
	ply:GetTable().LastDrunkMulUpdate = 0;
	ply:GetTable().LastDrunkWalkUpdate = 0;
	ply:GetTable().LastDrunkWalkMul = 0;
	
	ply:Conscious();

	--Compute player speeds on new character
	ply:ComputePlayerSpeeds();

	ply:ResetBleeding();
	ply:MakeNotInvisible();
	ply:SetTeam( 1 );
	
	--We're initialized and allow the player to move around again
	ply:GetTable().Initialized = true;
	ply:UnLock();
	
	ply:DrawViewModel( true );

	ply:CallEvent( "MapViewOff" );
	ply:SetNWBool( "StunStickHolstered", true );
	
	if( not ply:GetTable().InGame ) then
	
		timer.Simple( 6,	function()
			ply:CallEvent( "DrawAfterCredits" );
		end )	
		
	end	
	
	ply:GetTable().InGame = true
	
	ply:HandleUID( true )
	ply:HandleTeamSpawn()
	ply:Spawn()

end

-- lol buggy hax
function meta:CharacterLoadInitialize()
	
	local ply = self;
	
	if( ply:IsBot() ) then return end
	
	--Inventories
	ply:GetTable().Inventories = { }
	
	--Just a list of the items in our inventory
	ply:GetTable().InventoryList = { }
	
	--Serverside inventory grid.  CPU lag?  We'll see.
	ply:GetTable().InventoryGrid = { }
	
	for n = 1, TS.MaxInventories do
		
		ply:GetTable().Inventories[n] = { }
		ply:GetTable().Inventories[n].Name = "";
		ply:GetTable().Inventories[n].Width = 9;
		ply:GetTable().Inventories[n].Height = 6;
	
		ply:GetTable().InventoryGrid[n] = { }
	
		for x = 0, 8 do
		
			ply:GetTable().InventoryGrid[n][x] = { }
		
			for y = 0, 5 do
			
				ply:GetTable().InventoryGrid[n][x][y] = { }
				ply:GetTable().InventoryGrid[n][x][y].Filled = false;
			
			end
			
		end
		
	end
	
	ply:CallEvent( "ResetInventory" );
	
	ply:SetPlayerSprint( 100 );
	ply:SetPlayerConsciousness( 100 );
	ply:SetPlayerMoney( 200 );
	ply:SetPlayerBleeding( false );
	ply:SetPlayerCanSprint( true );
	ply:SetPlayerConscious( true );
	
	ply:SetHealth( 100 );
	ply:GetTable().MaxHealth = 100;
	
	ply:GetTable().OutOfMenu = true
	ply:GetTable().InGame = true
	
	ply:GetTable().StatusIsInjured = false;
	ply:GetTable().StatusIsCrippled = false;
	ply:GetTable().IsTied = false;
	
	ply:GetTable().LastDrunkMulUpdate = 0;
	ply:GetTable().LastDrunkWalkUpdate = 0;
	ply:GetTable().LastDrunkWalkMul = 0;
	
	ply:Conscious();

	--Compute player speeds on new character
	ply:ComputePlayerSpeeds();

	ply:ResetBleeding();
	ply:MakeNotInvisible();
	ply:SetTeam( 1 );
	
	--We're initialized and allow the player to move around again
	ply:GetTable().Initialized = true;
	ply:UnLock();
	
	ply:DrawViewModel( true );

	ply:CallEvent( "MapViewOff" );
	
	if( ply:GetPlayerChosenCharID() != -1 ) then
		ply:LoadCharacter( ply:GetPlayerChosenCharID() )
	end	
	
	ply:HandleUID( true )
	ply:HandleTeamSpawn()
	ply:Spawn()

end

function GM:PlayerSpawn( ply )	

	if( ply:IsBot() ) then return end

	if( not ply:GetTable().Initialized ) then
		ply:SetModel( "models/player.mdl" );
		ply:SetNoDraw( true );
		ply:SetNotSolid( true );
		return;
	end
	
	ply:SetNWBool( "SWEPHolstered", true )
	
	if( ply:GetTable().RagdollEntity and ply:GetTable().RagdollEntity:IsValid() ) then
		if( ply:GetTable().BypassUnconscious ) then
			ply:RemoveRagdoll();
			ply:GetTable().BypassUnconscious = false;
		else
			ply:MakeInvisible();
			ply:CrosshairDisable();
			ply:SetPos( ply:GetTable().RagdollEntity:GetPos() );
			ply:Freeze( true );
			return;
		end
	end
	
	if( ply:GetTable().SpawnPosition ) then
	
		ply:SetPos( ply:GetTable().SpawnPosition );
		ply:GetTable().SpawnPosition = nil;
	
	end
	
	ply:SetPlayerDrunkMul( 0 );
	ply:CallEvent( "NoDrunk" );
	
	ply:GetTable().IsTied = false;
	

	umsg.Start( "TOFFOWS", ply ); umsg.End();

	ply:CrosshairDisable();
	
	ply:GetTable().LastWeapon = nil;
	
	ply:ResetBodyDamage();
	ply:ResetBleeding();
	
	--ply:HandleTeamSpawn();
	timer.Simple( .2, ply.HandleTeamSpawn, ply );

	ply:SetPlayerSprint( 100 );
	ply:SetPlayerConsciousness( 100 );
	
	if( ply:HasTT() ) then
		ply:Give( "gmod_tool" );
	end
	
	ply:Give( "weapon_physgun" );
	ply:Give( "weapon_physcannon" );
	ply:Give( "ts2_hands" );
	ply:Give( "ts2_keys" );
	
	ply:SelectWeapon( "ts2_hands" );
	
	ply:ComputePlayerSpeeds();


end

function GM:PlayerDeathSound()
	
	return true;

end

function GM:CanPlayerSuicide( ply )

	if( ply:IsTied() or not ply:GetPlayerConscious() ) then
	
		return false;
	
	end
	
	return true;

end

function GM:PlayerDeath( ply, weapon, attacker )

	if( attacker:IsPlayer() ) then

		if( attacker != ply ) then
		
			if( ply:IsCombine() ) then
			
				ply:RadioTalk( "[" .. ply:GetRPName() .. "] Biosignal has been lost", true )
				
				umsg.Start( "BSL", ply )
					umsg.String( ply:GetRPName() )
				umsg.End()
						
				for k, v in pairs( player.GetAll() ) do
			
					if( v:IsCombineDefense() ) then
				
						v:EmitSound( "npc/overwatch/radiovoice/lostbiosignalforunit.wav" )
					
						v:EmitSound( "HL1/fvox/flatline.wav", 50, 100 )
											
					end
				
				end	
			
			end
			
		end	
		
	end	

	if( ply:HasCPModel() ) then
	
		local num = math.random( 1, 4 );
		
		ply:EmitSound( Sound( "npc/metropolice/die" .. num .. ".wav" ) );
		ply:EmitSound( "HL1/fvox/flatline.wav", 50, 100 )
		
	end
	
	if( ply:IsOW() or ply:IsOWElite() ) then
	
		local num = math.random( 1, 3 );
		
		ply:EmitSound( Sound( "npc/combine_soldier/die" .. num .. ".wav" ) );
	
	end

	local makeragdoll = true;
	
	ply:GetTable().ForceDeath = false;

	if( not ply:GetTable().BypassUnconscious ) then

		if( not ply:GetPlayerConscious() ) then
			ply:PrintMessage( 3, "Killing yourself during KO removes all your weapons" );
			ply:TakeAllInventoryWeapons();
			ply:Freeze( false );
			return;
		end
		
	elseif( not ply:GetPlayerConscious() ) then

		ply:Conscious();
		makeragdoll = false;
		
	end
	

	for k, v in pairs( ply:GetTable().ProcessBars ) do
	
		ply:GetTable().ProcessBars[k] = nil;
	
	end
	
	umsg.Start( "RAPB", ply ); umsg.End();
	
	if( ply:HasTT() ) then
		ply:Give( "gmod_tool" )
	end

	ply:GetTable().HasTempWeapon = false;
	
	if( ply:GetActiveWeapon():IsValid() ) then
	
		local class = ply:GetActiveWeapon():GetClass();
		
		if( string.find( class, "ts2_" ) and
			class ~= "ts2_base" and
			class ~= "ts2_hands" and
			class ~= "ts2_kanyewest" and
			class ~= "ts2_keys" and
			class ~= "ts2_mapeditor" ) then
			
			TS.CreateItemProp( class, ply:GetActiveWeapon():GetPos(), ply:GetActiveWeapon():GetAngles() );
			
		end
	
	end

	ply:SnapOutOfStance();

	if( not ply:IsCombine() ) then
		ply:TakeAllInventoryWeapons();
	end	
	
	-- omg shity code lol!!!
	timer.Simple( 4, function()
	
		if( ply:IsCombine() ) then
			
			for i, v in pairs( ply:GetTable().InventoryGrid ) do
		
				for x, c in pairs( v ) do
			
					for y, u in pairs( c ) do
					
						if( ply:GetTable().InventoryGrid[i][x][y].ItemData ) then
					
							if( string.find( ply:GetTable().InventoryGrid[i][x][y].ItemData.ID, "ts2_" ) and
								ply:GetTable().InventoryGrid[i][x][y].ItemData.ID ~= "ts2_hands" ) then
									
								ply:Give( ply:GetTable().InventoryGrid[i][x][y].ItemData.ID )
									
							end
							
						end

					end

				end

			end

		end
		
	end )

end		


function GM:PlayerConnect( name, address )

	umsg.Start( "PlyCon" );
		umsg.String( name );
	umsg.End();
	
	TS.PrintMessageAll( 2, name .. " has connected" );

end
 
function GM:PlayerDisconnected( ply )

	ply:SnapOutOfStance();

	if( ply:GetTable().RagdollEntity and ply:GetTable().RagdollEntity:IsValid() ) then
		ply:GetTable().RagdollEntity:Remove();
	end

	umsg.Start( "PlyDisc" );
		umsg.String( ply:GetRPName() );
		umsg.String( ply:Nick() );
		umsg.String( ply:SteamID() );
	umsg.End();
	
	--ply:UpdateCharacter()

	TS.PrintMessageAll( 2, ply:GetRPName() .. " (SF: " .. ply:Nick() .. " ID: " .. ply:SteamID() .. ") has left the server" );
		
end

function GM:PlayerTraceAttack()

	return false;

end

function GM:ScalePlayerDamage( ply, hitgroup, dmginfo )

	if( not ply:GetTable().Initialized ) then return; end

	if( not dmginfo:GetAttacker():IsPlayer() and not dmginfo:GetAttacker():IsNPC() ) then
		return;
	end

	if( ply:GetTable().ObserveMode ) then
		dmginfo:SetDamage( -1000 );
		return dmginfo;
	end

	if( ply:GetTable().NoclipMode ) then
		dmginfo:SetDamage( -1000 );
		return dmginfo;
	end

	if( ply:GetActiveWeapon():IsValid() and ply:GetActiveWeapon():GetClass() == "ts2_kanyewest" ) then
		dmginfo:SetDamage( -1000 );
		return dmginfo;
	end

	ply:SnapOutOfStance();
	
	local weapon = dmginfo:GetInflictor();
	
	if( weapon:IsPlayer() or weapon:IsNPC() ) then
		weapon = weapon:GetActiveWeapon();
	end

	if( weapon:IsValid() and weapon:IsWeapon() ) then
	
		return ply:ScaleDamageFromAttack( dmginfo:GetInflictor(), weapon, hitgroup, dmginfo );
	
	end	
	
	dmginfo:SetDamage( -1000 );
	return dmginfo;
	
end


function GM:PlayerFootstep( ply, pos, foot, sound, volume, rf )  

    if( ply:IsCP() and ply:IsSprinting() ) then    
	
	   local num = math.random( 1, 6 );		
	   ply:EmitSound( Sound( "npc/metropolice/gear" .. num .. ".wav" ), 50, 100 );	  
	   
    elseif( ply:IsCP() and ply:IsWalking() ) then     
	
       local ft = math.random( 1, 3 );		  	
       ply:EmitSound( Sound( "player/footsteps/tile" .. ft .. ".wav" ), 45, 100 );	
	   
	end   
	
	if( ply:IsCOTA() and ply:IsSprinting() ) then
	
	   local num = math.random( 1, 6 );
	   ply:EmitSound( Sound( "npc/combine_soldier/gear" .. num .. ".wav" ), 50, 100 );	
	   
	end

end	


function GM:Move( ply, mv )

	if( ply:GetTable().InStanceAction ) then
	
		return true;
	
	end

end

function GM:GravGunPunt( ply ) 

	if( ply:IsWaffler() ) then
		return true;
	end
	
	return false;
	
end

function GM:PlayerSpawnVehicle( ply )

	if( ply:IsAdmin() ) then return true; end

end

function GM:PlayerSpawnSENT( ply, name )
		
	if( ply:IsAdmin() or ply:IsTrusted() ) then return true; end
	
end

function GM:PlayerSpawnNPC( ply, npc_type, equipment )

	if( ply:IsAdmin() ) then return true; end
	
end

function GM:PlayerSpawnRagdoll( ply, model )

	if ply:IsUserGroup("dolls") or ply:IsAdmin() then return true; end

	
end

function GM:PlayerSpawnEffect( ply, model )
	
	if( ply:IsAdmin() ) then return true; end
	

end


